﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace PsqlDotnet.Model.Schema
{
    public class Table : ITable
    {
        public Table(string name)
        {
            if (String.IsNullOrWhiteSpace(name))
                throw new ArgumentException("Invalid null or empty table name");

            columns = new List<Column>();
            constraints = new List<IConstraint>();
            Name = name;
        }

        #region ITable Members

        public string Name { get; set; }

        public ReadOnlyCollection<Column> Columns
        {
            get
            {
                return columns.AsReadOnly();
            }
        }

        public ReadOnlyCollection<IConstraint> Constraints
        {
            get
            {
                return constraints.AsReadOnly();
            }
        }

        public int ColumnCount
        {
            get
            {
                return columns.Count;
            }
        }

        /// <summary>
        /// Adds column into table. If column with given name already exists in table does nothing and returns false
        /// </summary>
        /// <param name="column">Column to be added to the table</param>
        /// <returns>True if column has been successfully added, false otherwise</returns>
        public bool AddColumn(Column column)
        {
            if (column == null)
                return false;

            if (columns.Where(c => c.Name == column.Name).Count() > 0)
                return false;

            columns.Add(column);
            column.Parent = Name;

            return true;
        }

        /// <summary>
        /// Removes column from table. If column doesn't exist does nothing and returns false
        /// </summary>
        /// <param name="column">Column to be removed from table</param>
        /// <returns>True if column has been successfully removed, false otherwise</returns>
        public bool RemoveColumn(Column column)
        {
            if (column == null)
                return false;

            return columns.Remove(column);
        }

        /// <summary>
        /// Removes column from table. If column with given name doesn't exist does nothing and returns false
        /// </summary>
        /// <param name="column">Column to be removed from table</param>
        /// <returns>True if column has been successfully removed, false otherwise</returns>
        public bool RemoveColumn(string columnName)
        {
            var column = columns.Where(c => c.Name == columnName).FirstOrDefault();

            if (column == null)
                return false;

            return columns.Remove(column);
        }

        /// <summary>
        /// Adds relation into given table. If relation's sourceTable isn't the same as the current one
        /// does nothing
        /// </summary>
        public bool AddConstraint(IConstraint constraint)
        {
            if (!ValidateConstraint(constraint))
                return false;

            if (constraints.Where(r => r.Name == constraint.Name).Count() > 0)
                return false;

            constraints.Add(constraint);
            return true;
        }

        /// <summary>
        /// Removes relation from table. If relation's sourceTable isn't the same as the current one
        /// does nothing
        /// </summary>
        public bool RemoveConstraint(IConstraint constraint)
        {
            if (constraint == null)
                return false;

            if ( constraint.SourceTable != Name)
                return false;

            var existingRelation = constraints.Where(r => r.Name == constraint.Name).FirstOrDefault();
            return constraints.Remove(existingRelation);
        }

        /// <summary>
        /// Removes relation with given name from table. If relation's sourceTable isn't the same as the current one
        /// does nothing
        /// </summary>
        public bool RemoveConstraint(string constraintName)
        {
            var existingRelation = constraints.Where(r => r.Name == constraintName).FirstOrDefault();
            return constraints.Remove(existingRelation);
        }

        #endregion

        #region Private fields

        private bool ValidateConstraint(IConstraint constraint)
        {
            if (constraint == null)
                return false;

            if (constraint.SourceTable != Name)
                return false;

            if (String.IsNullOrWhiteSpace(constraint.Name))
                return false;

            return true;
        }

        #endregion

        private List<Column> columns;
        private List<IConstraint> constraints;
    }
}
